#include "uart.h"
#include <stdio.h>
#include <stdarg.h>

volatile unsigned long long m_rx_previous_time = 0; // 上一次进入中断时间
UartStr g_uartMN;

void Uart_SetCount(uint32_t us)
{
    __HAL_TIM_SET_COUNTER(&htim6, us); // 设置定时器初始�??
}

uint32_t Uart_GetCount()
{
    return __HAL_TIM_GET_COUNTER(&htim6); // 获取定时器当前计�?
}

void Uart_StartCount(void)
{
	__HAL_TIM_SET_COUNTER(&htim6, 0); // 设置定时器初始�??
	__HAL_TIM_CLEAR_IT(&htim6, TIM_IT_UPDATE);
	HAL_TIM_Base_Start_IT(&htim6); // 启动定时�?
}

void Uart_StopCount(void)
{
    HAL_TIM_Base_Stop_IT(&htim6); // 停止定时�?
}


u8 Uart_GetRxPinLevel(void)
{
    return HAL_GPIO_ReadPin(VIRTUAL_UART_RX_GPIO_Port, VIRTUAL_UART_RX_Pin);
}

void Uart_SetTxPinLevel(u8 level)
{
	 HAL_GPIO_WritePin(VIRTUAL_UART_TX_GPIO_Port, VIRTUAL_UART_TX_Pin, level);
}

void Uart_Init(void)
{
    g_uartMN.config.stopBit = 1;
    g_uartMN.config.dataBit = 8;
    g_uartMN.config.parityBit = 0;
    g_uartMN.config.baudRate = 9600; /* 每秒传输的bit */
    g_uartMN.config.bitSpace = (1 * 1000 * 1000) / g_uartMN.config.baudRate; /* 算出每个bit传输的时间 */
	g_uartMN.config.totalBit = g_uartMN.config.dataBit;
	g_uartMN.config.deviation = 20; /* 误差范围，防止出现波动导致检测失败 */

	g_uartMN.ctrl.currentBit = 0;
	g_uartMN.ctrl.lastBit = 0;
	g_uartMN.ctrl.state = UART_IDEL;
	g_uartMN.ctrl.skipBit = 0;
    g_uartMN.recLen = 0;
}

u8 UartIsBegin(void)
{
    return g_uartMN.ctrl.state == UART_IDEL; // 判断是否是起始位
}

void Uart_ClaerCtrlPara(void)
{
	g_uartMN.ctrl.currentBit = 0;
	g_uartMN.ctrl.lastBit = 0;
	g_uartMN.ctrl.lastTimes = 0;
	g_uartMN.ctrl.skipBit = 0;
}

void Uart_DealBit(u8 mode)
{
	if (mode == 1) /* 外部中断 */
	{
		// 数据长度超出总长度
		if ((g_uartMN.ctrl.skipBit + g_uartMN.ctrl.currentBit) > g_uartMN.config.totalBit) {
			g_uartMN.ctrl.skipBit = g_uartMN.config.totalBit - g_uartMN.ctrl.currentBit; /* 直接把位放到后面 */
		}
	} else { /* 定时器中断 */
		g_uartMN.ctrl.skipBit = g_uartMN.config.totalBit - g_uartMN.ctrl.currentBit; /* 直接把位放到后面 */
		g_uartMN.ctrl.lastBit = 1;
	}

	for (u32 i = 0; i < g_uartMN.ctrl.skipBit; i++)
	{ // 根据几个数据 给予相应的位
		g_uartMN.ctrl.bitBuf[g_uartMN.ctrl.currentBit + i] = g_uartMN.ctrl.lastBit; // change +1
	}
	g_uartMN.ctrl.currentBit += g_uartMN.ctrl.skipBit;

	// 数据已接收至结束位
	if (g_uartMN.ctrl.currentBit >= g_uartMN.config.totalBit)
	{
		if (g_uartMN.recLen < UART_MAXLEN)
		{
			g_uartMN.recBuf[g_uartMN.recLen++] = (g_uartMN.ctrl.bitBuf[7] << 7) |
											(g_uartMN.ctrl.bitBuf[6] << 6) | (g_uartMN.ctrl.bitBuf[5] << 5) | (g_uartMN.ctrl.bitBuf[4] << 4) | (g_uartMN.ctrl.bitBuf[3] << 3) |
											(g_uartMN.ctrl.bitBuf[2] << 2) | (g_uartMN.ctrl.bitBuf[1] << 1) | g_uartMN.ctrl.bitBuf[0];
		}
		g_uartMN.ctrl.state = UART_IDEL;
		Uart_ClaerCtrlPara();
		Uart_StopCount();
	}
}

void UartReciverOneChar(void)
{
	// 当前未开始一个字节的接收且此时为下降沿
	if (UartIsBegin()) // 起始位
	{ // 10 当数据不合法时或者结束传输时 g_uartMN.ctrl.currentBit值设为10
		if (!Uart_GetRxPinLevel())
		{	// 下降沿
			g_uartMN.ctrl.state = UART_BEGIN; // 记下开始接收
            Uart_StartCount(); // 开启一个计数，时间基数1us，一个bit大约104us，1byte = 10bit * 104us = 1000us = 1ms
		}
		Uart_ClaerCtrlPara();
		return;
	}

	// 已经开始接收
	u32 time = Uart_GetCount();					  // 记下此刻时间
	u32 spaceTime = (time - g_uartMN.ctrl.lastTimes) + g_uartMN.config.deviation; // 计算一个状态持续的时长
	g_uartMN.ctrl.lastTimes = time;								  // 为下次计算时长做准备
	// 计算二进制数据的个数
	g_uartMN.ctrl.skipBit = spaceTime / g_uartMN.config.bitSpace;

	if (g_uartMN.ctrl.state == UART_BEGIN)
	{
		if (g_uartMN.ctrl.skipBit >= 1)
		{
			g_uartMN.ctrl.skipBit -= 1;
		}
		g_uartMN.ctrl.lastBit = (g_uartMN.ctrl.skipBit >= 1) ? 0 : 1;
		g_uartMN.ctrl.state = UART_TRAN;
	} else {
		g_uartMN.ctrl.lastBit = !Uart_GetRxPinLevel();
	}

	Uart_DealBit(1);
}

void Uart_SendByte(u8 val)
{
	u16 i;

	Uart_SetTxPinLevel(0);			  // 拉低 开始传输
	DelayUs(g_uartMN.config.bitSpace); // 波特率根据延时在设置

	for (i = 0; i < 8; i++)
	{
		if (val & 0x1) // 发送bit位
		{ 
     Uart_SetTxPinLevel(1);
		}
		else
		{
			Uart_SetTxPinLevel(0);
		}
		val >>= 1;
		DelayUs(g_uartMN.config.bitSpace);
	}

	Uart_SetTxPinLevel(1);
	DelayUs(g_uartMN.config.bitSpace);
}

void Uart_SendStr(u8 *st, u16 len)
{
	int i = 0;
	while ((len--) != 0)
	{
		Uart_SendByte(st[i]);
		i++;
	}
}

u16 Uart_GetRecLen(void)
{
    return g_uartMN.recLen;
}

void Uart_SetRecLen(u16 len)
{
    g_uartMN.recLen = len;
}

u8* Uart_GetRecData(void)
{
    return &g_uartMN.recBuf[0];
}

static char sprint_buf[256];
u16 Uart_Printf(const char *fmt, ...)
{
    va_list args;
    int n;
    // 第一个可变形参指针
    va_start(args, fmt);
    // 根据字符串fmt，将对应形参转换为字符串，并组合成新的字符串存储在sprint_buf[]缓存中，返回字符个数。
    n = vsprintf(sprint_buf, fmt, args);
    //c标准要求在同一个函数中va_start 和va_end 要配对的出现。
    va_end(args);
    // 调用相关驱动接口,将将sprintf_buf中的内容输出n个字节到设备，
    // 此处可以是串口、控制台、Telnet等,在嵌入式开发中可以灵活挂接
	Uart_SendStr(sprint_buf, n);
    return n;
}